package com.xw.unification.utils;

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;

public abstract class AnnotationDetector {

    public static <T extends Annotation> T findAnnotation(Method method, Class<T> annotationType) {
        return findAnnotation(method, annotationType, true);
    }

    public static <T extends Annotation> T findAnnotation(Class<?> type, Class<T> annotationType) {
        return findAnnotation(type, annotationType, true);
    }

    public static <T extends Annotation> T findAnnotation(AnnotatedElement annotatedElement, Class<T> annotationType) {
        return AnnotationUtils.findAnnotation(annotatedElement, annotationType);
    }

    public static <T extends Annotation> T findAnnotation(HandlerMethod handlerMethod, Class<T> annotationType) {
        if (handlerMethod != null && handlerMethod.getMethod() != null) {
            return findAnnotation(handlerMethod.getMethod(), annotationType, true);
        } else {
            return null;
        }
    }

    public static <T extends Annotation> T findClassAnnotation(HandlerMethod handlerMethod, Class<T> annotationType) {
        if (handlerMethod != null && handlerMethod.getMethod() != null && handlerMethod.getMethod().getDeclaringClass() != null) {
            return AnnotationUtils.findAnnotation(handlerMethod.getMethod().getDeclaringClass(), annotationType);
        } else {
            return null;
        }
    }

    public static <T extends Annotation> T findAnnotation(Method method, Class<T> annotationType, boolean inherit) {
        if (method != null) {
            return inherit ? AnnotationUtils.findAnnotation(method, annotationType)
                    : method.getDeclaredAnnotation(annotationType);
        } else {
            return null;
        }
    }

    public static <T extends Annotation> T findAnnotation(Class<?> type, Class<T> annotationType, boolean inherit) {
        if (type != null) {
            return inherit ? AnnotationUtils.findAnnotation(type, annotationType)
                    : type.getDeclaredAnnotation(annotationType);
        } else {
            return null;
        }
    }

    public static <T extends Annotation> T findAnnotation(HandlerMethod handlerMethod, Class<T> annotationType, boolean inherit) {
        if (handlerMethod != null && handlerMethod.getMethod() != null) {
            return findAnnotation(handlerMethod.getMethod(), annotationType, inherit);
        } else {
            return null;
        }
    }

    public static <T extends Annotation> T findClassAnnotation(HandlerMethod handlerMethod, Class<T> annotationType, boolean inherit) {
        if (handlerMethod != null && handlerMethod.getMethod() != null
                && handlerMethod.getMethod().getDeclaringClass() != null) {
            return findAnnotation(handlerMethod.getMethod().getDeclaringClass(), annotationType, inherit);
        } else {
            return null;
        }
    }

}
